home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
programming
/
other
/
jikes
/
src
/
zip.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
13KB
|
399 lines
// $Id: zip.cpp,v 1.3 1999/01/25 20:00:32 shields Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://www.ibm.com/research/jikes.
// Copyright (C) 1996, 1998, International Business Machines Corporation
// and others. All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
#include "config.h"
#include <assert.h>
#include <iostream.h>
#include <string.h>
#include "control.h"
#include "zip.h"
#include "symbol.h"
//************************************************************************************************
//
// The ZipFile methods follow
//
//************************************************************************************************
#if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
int (*ZipFile::uncompress_file[10]) (FILE *, char *, long) =
{
UncompressFile0,
UncompressFile1,
UncompressFile2,
UncompressFile3,
UncompressFile4,
UncompressFile5,
UncompressFile6,
UncompressFile7,
UncompressFile8,
UncompressFile9
};
inline u1 ZipFile::GetU1()
{
return getc(zipfile);
}
inline void ZipFile::Skip(u4 length)
{
for (u4 i = 0; i < length; i++)
getc(zipfile);
}
#elif defined(WIN32_FILE_SYSTEM)
int (*ZipFile::uncompress_file[10]) (char *, char *, long) =
{
UncompressFile0,
UncompressFile1,
UncompressFile2,
UncompressFile3,
UncompressFile4,
UncompressFile5,
UncompressFile6,
UncompressFile7,
UncompressFile8,
UncompressFile9
};
inline u1 ZipFile::GetU1()
{
return *file_buffer++;
}
inline void ZipFile::Skip(u4 length)
{
file_buffer += length;
}
#endif
inline u2 ZipFile::GetU2()
{
u4 val = GetU1();
val |= (((u4) GetU1()) << 8);
return val;
}
inline u4 ZipFile::GetU4()
{
u4 val = GetU1();
val |= (((u4) GetU1()) << 8);
val |= (((u4) GetU1()) << 16);
val |= (((u4) GetU1()) << 24);
return val;
}
ZipFile::ZipFile(FileSymbol *file_symbol) : buffer(NULL)
{
Zip *zip = file_symbol -> Zipfile();
#if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
zipfile = zip -> zipfile;
int rc = fseek(zipfile, file_symbol -> offset, SEEK_SET);
assert(rc == 0);
#elif defined(WIN32_FILE_SYSTEM)
file_buffer = &zip -> zipbuffer[file_symbol -> offset];
#endif
Skip(8); // u4 magic = GetU4();
// u2 version_needed_to_extract = GetU2();
// u2 general_purpose_bits = GetU2();
u2 compression_method = GetU2();
Skip(16); // u2 time = GetU2();
// u2 date = GetU2();
// u4 crc32 = GetU4();
// u4 compressed_size = GetU4();
// u4 uncompressed_size = GetU4();
u2 filename_length = GetU2();
u2 extra_field_length = GetU2();
Skip(filename_length + extra_field_length);
#if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
this -> buffer = new char[file_symbol -> uncompressed_size];
if (! uncompress_file[compression_method < 9 ? compression_method : 9](zipfile, this -> buffer, file_symbol -> uncompressed_size))
{
delete [] this -> buffer;
this -> buffer = NULL;
}
#elif defined(WIN32_FILE_SYSTEM)
if (compression_method > 0)
{
this -> buffer = new char[file_symbol -> uncompressed_size];
if (! uncompress_file[compression_method < 9 ? compression_method : 9](file_buffer,
this -> buffer,
file_symbol -> uncompressed_size))
{
delete [] this -> buffer;
this -> buffer = NULL;
this -> file_buffer = NULL;
}
}
#endif
return;
}
ZipFile::~ZipFile()
{
delete [] buffer;
}
//************************************************************************************************
//
// The Zip methods follow:
//
//************************************************************************************************
inline u1 Zip::GetU1()
{
return *buffer_ptr++;
}
inline u2 Zip::GetU2()
{
u4 val = GetU1();
val |= (((u4) GetU1()) << 8);
return val;
}
inline u4 Zip::GetU4()
{
u4 val = GetU1();
val |= (((u4) GetU1()) << 8);
val |= (((u4) GetU1()) << 16);
val |= (((u4) GetU1()) << 24);
return val;
}
inline void Zip::Skip(u4 length)
{
buffer_ptr += length;
}
inline DirectorySymbol *Zip::ProcessSubdirectoryEntries(DirectorySymbol *directory_symbol, char *name, int name_length)
{
wchar_t *directory_name = new wchar_t[name_length];
for (int start = 0, end; start < name_length; start = end + 1)
{
end = start;
for (int i = 0; end < name_length && name[end] != U_SLASH; i++, end++)
directory_name[i] = name[end];
NameSymbol *name_symbol = control.FindOrInsertName(directory_name, end - start);
DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
if (! subdirectory_symbol)
subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
directory_symbol = subdirectory_symbol;
}
delete [] directory_name;
return directory_symbol;
}
inline NameSymbol *Zip::ProcessFilename(char *name, int name_length)
{
wchar_t *input_filename = new wchar_t[name_length];
for (int i = 0; i < name_length; i++)
input_filename[i] = name[i];
NameSymbol *name_symbol = control.FindOrInsertName(input_filename, name_length);
delete [] input_filename;
return name_symbol;
}
inline void Zip::ProcessDirectoryEntry(DirectorySymbol *directory_symbol)
{
Skip(8); // u2 version_made_by = GetU2();
// u2 version_needed_to_extract = GetU2();
// u2 general_purpose_bits = GetU2();
// u2 compression_method = GetU2();
u2 last_mod_file_time = GetU2();
u2 last_mod_file_date = GetU2();
Skip(4); // u4 crc32 = GetU4();
Skip(4); // u4 compressed_size = GetU4();
u4 uncompressed_size = GetU4();
u2 file_name_length = GetU2();
u2 extra_field_length = GetU2();
u2 file_comment_length = GetU2();
Skip(8); // u2 disk_number_start = GetU2();
// u2 internal_file_attributes = GetU2();
// u4 external_file_attributes = GetU4();
u4 relative_offset_of_local_header = GetU4();
u4 date_time = ((u4) last_mod_file_date) << 16 | last_mod_file_time;
char *name = buffer_ptr;
Skip(file_name_length + extra_field_length + file_comment_length);
//
// Note that we need to process all subdirectory entries that appear in the zip file, and not
// just the ones that contain java and class files. Recall that in java the dot notation is
// used in specifying a package. Therefore, in processing a qualified-name that represents
// a package, we need to recognize each name as a subpackage. E.g., when processing
// "java.lang", we need to recognize "java" as a package before looking for "lang"...
//
if (name[file_name_length - 1] == U_SLASH)
ProcessSubdirectoryEntries(directory_symbol, name, file_name_length - 1); // -1 to remove last '/'
else
{
bool java_file = (file_name_length >= FileSymbol::java_suffix_length &&
FileSymbol::IsJavaSuffix(&name[file_name_length - FileSymbol::java_suffix_length])),
class_file = (file_name_length >= FileSymbol::class_suffix_length &&
FileSymbol::IsClassSuffix(&name[file_name_length - FileSymbol::class_suf